home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
C/C++ Users Group Library 1996 July
/
C-C++ Users Group Library July 1996.iso
/
vol_100
/
198_02
/
isearch.c
< prev
next >
Wrap
C/C++ Source or Header
|
1990-01-21
|
19KB
|
509 lines
/*
* The functions in this file implement commands that perform incremental
* searches in the forward and backward directions. This "ISearch" command
* is intended to emulate the same command from the original EMACS
* implementation (ITS). Contains references to routines internal to
* SEARCH.C.
*
* REVISION HISTORY:
*
* D. R. Banks 9-May-86
* - added ITS EMACSlike ISearch
*
* John M. Gamble 5-Oct-86
* - Made iterative search use search.c's scanner() routine.
* This allowed the elimination of bakscan().
* - Put isearch constants into estruct.h
* - Eliminated the passing of 'status' to scanmore() and
* checknext(), since there were no circumstances where
* it ever equalled FALSE.
*/
#include <stdio.h>
#include "estruct.h"
#include "edef.h"
#if ISRCH
extern int scanner(); /* Handy search routine */
extern int eq(); /* Compare chars, match case */
/* A couple of "own" variables for re-eat */
int (*saved_get_char)(); /* Get character routine */
int eaten_char = -1; /* Re-eaten char */
/* A couple more "own" variables for the command string */
int cmd_buff[CMDBUFLEN]; /* Save the command args here */
int cmd_offset; /* Current offset into command buff */
int cmd_reexecute = -1; /* > 0 if re-executing command */
/*
* Subroutine to do incremental reverse search. It actually uses the
* same code as the normal incremental search, as both can go both ways.
*/
int risearch(f, n)
{
LINE *curline; /* Current line on entry */
int curoff; /* Current offset on entry */
/* remember the initial . on entry: */
curline = curwp->w_dotp; /* Save the current line pointer */
curoff = curwp->w_doto; /* Save the current offset */
/* Make sure the search doesn't match where we already are: */
backchar(TRUE, 1); /* Back up a character */
if (!(isearch(f, -n))) /* Call ISearch backwards */
{ /* If error in search: */
curwp->w_dotp = curline; /* Reset the line pointer */
curwp->w_doto = curoff; /* and the offset to original value */
curwp->w_flag |= WFMOVE; /* Say we've moved */
update(FALSE); /* And force an update */
mlwrite ("[search failed]"); /* Say we died */
} else mlerase (); /* If happy, just erase the cmd line */
}
/* Again, but for the forward direction */
int fisearch(f, n)
{
LINE *curline; /* Current line on entry */
int curoff; /* Current offset on entry */
/* remember the initial . on entry: */
curline = curwp->w_dotp; /* Save the current line pointer */
curoff = curwp->w_doto; /* Save the current offset */
/* do the search */
if (!(isearch(f, n))) /* Call ISearch forwards */
{ /* If error in search: */
curwp->w_dotp = curline; /* Reset the line pointer */
curwp->w_doto = curoff; /* and the offset to original value */
curwp->w_flag |= WFMOVE; /* Say we've moved */
update(FALSE); /* And force an update */
mlwrite ("[search failed]"); /* Say we died */
} else mlerase (); /* If happy, just erase the cmd line */
}
/*
* Subroutine to do an incremental search. In general, this works similarly
* to the older micro-emacs search function, except that the search happens
* as each character is typed, with the screen and cursor updated with each
* new search character.
*
* While searching forward, each successive character will leave the cursor
* at the end of the entire matched string. Typing a Control-S or Control-X
* will cause the next occurrence of the string to be searched for (where the
* next occurrence does NOT overlap the current occurrence). A Control-R will
* change to a backwards search, META will terminate the search and Control-G
* will abort the search. Rubout will back up to the previous match of the
* string, or if the starting point is reached first, it will delete the
* last character from the search string.
*
* While searching backward, each successive character will leave the cursor
* at the beginning of the matched string. Typing a Control-R will search
* backward for the next occurrence of the string. Control-S or Control-X
* will revert the search to the forward direction. In general, the reverse
* incremental search is just like the forward incremental search inverted.
*
* In all cases, if the search fails, the user will be feeped, and the search
* will stall until the pattern string is edited back into something that
* exists (or until the search is aborted).
*/
isearch(f, n)
{
int status; /* Search status */
int col; /* prompt column */
register int cpos; /* character number in search string */
register int c; /* current input character */
register int expc; /* function expanded input char */
char pat_save[NPAT]; /* Saved copy of the old pattern str */
LINE *curline; /* Current line on entry */
int curoff; /* Current offset on entry */
int init_direction; /* The initial search direction */
/* Initialize starting conditions */
cmd_reexecute = -1; /* We're not re-executing (yet?) */
cmd_offset = 0; /* Start at the beginning of the buff */
cmd_buff[0] = '\0'; /* Init the command buffer */
bytecopy (pat_save, pat, NPAT-1); /* Save the old pattern string */
curline = curwp->w_dotp; /* Save the current line pointer */
curoff = curwp->w_doto; /* Save the current offset */
init_direction = n; /* Save the initial search direction */
/* This is a good place to start a re-execution: */
start_over:
/* ask the user for the text of a pattern */
col = promptpattern("ISearch: "); /* Prompt, remember the col */
cpos = 0; /* Start afresh */
status = TRUE; /* Assume everything's cool */
/*
Get the first character in the pattern. If we get an initial Control-S
or Control-R, re-use the old search string and find the first occurrence
*/
c = ectoc(expc = get_char()); /* Get the first character */
if ((c == IS_FORWARD) ||
(c == IS_REVERSE) ||
(c == IS_VMSFORW)) /* Reuse old search string? */
{
for (cpos = 0; pat[cpos] != 0; cpos++) /* Yup, find the length */
col = echochar(pat[cpos],col); /* and re-echo the string */
if (c == IS_REVERSE) { /* forward search? */
n = -1; /* No, search in reverse */
backchar (TRUE, 1); /* Be defensive about EOB */
} else
n = 1; /* Yes, search forward */
status = scanmore(pat, n); /* Do the search */
c = ectoc(expc = get_char()); /* Get another character */
}
/* Top of the per character loop */
for (;;) /* ISearch per character loop */
{
/* Check for special characters first: */
/* Most cases here change the search */
if (expc == metac) /* Want to quit searching? */
return (TRUE); /* Quit searching now */
switch (c) /* dispatch on the input char */
{
case IS_ABORT: /* If abort search request */
return(FALSE); /* Quit searching again */
case IS_REVERSE: /* If backward search */
case IS_FORWARD: /* If forward search */
case IS_VMSFORW: /* of either flavor */
if (c == IS_REVERSE) /* If reverse search */
n = -1; /* Set the reverse direction */
else /* Otherwise, */
n = 1; /* go forward */
status = scanmore(pat, n); /* Start the search again */
c = ectoc(expc = get_char()); /* Get the next char */
continue; /* Go continue with the search*/
case IS_NEWLINE: /* Carriage return */
c = '\n'; /* Make it a new line */
break; /* Make sure we use it */
case IS_QUOTE: /* Quote character */